# aclnn_gen/generation/cmake_generator.py
from aclnn_gen.parsing.op_parser import OperatorDefinition

class CMakeGenerator:
    """
    Generates the content for the CMakeLists.txt file for a flat project structure.
    """

    def __init__(self, op_def: OperatorDefinition, cpp_filename: str):
        """
        Initializes the CMakeGenerator.

        Args:
            op_def (OperatorDefinition): The parsed operator prototype definition.
            cpp_filename (str): The name of the main C++ source file.
        """
        self.op_def = op_def
        self.cpp_filename = cpp_filename

    def generate_content(self) -> str:
        """
        Creates the full content of the CMakeLists.txt file as a string.
        """
        project_name = self.op_def.op_name_snake
        executable_name = f"execute_{project_name}_op"

        return f"""# CMake lowest version requirement
cmake_minimum_required(VERSION 3.5.1)

# Project information
project(acl_execute_{project_name})

# Compile options
add_compile_options(-std=c++11 -fstack-protector-all -D_FORTIFY_SOURCE=2 -O2)
set(CMAKE_CXX_FLAGS "${{CMAKE_CXX_FLAGS}} -Wl,-z,relro,-z,now,-z,noexecstack")

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "./")

set(INC_PATH $ENV{{DDK_PATH}})

if (NOT DEFINED ENV{{DDK_PATH}})
    set(INC_PATH "/usr/local/Ascend/ascend-toolkit/latest")
    message(STATUS "set default INC_PATH: ${{INC_PATH}}")
else ()
    message(STATUS "env INC_PATH: ${{INC_PATH}}")
endif()

if(NOT DEFINED ENV{{ASCEND_CUSTOM_OPP_PATH}})
    set(CUST_PKG_PATH "${{INC_PATH}}/opp/vendors/customize/op_api")
    message(STATUS "set default CUST_PKG_PATH: ${{CUST_PKG_PATH}}")
else()
    string(REPLACE ":" ";" OPP_PATH_LIST "$ENV{{ASCEND_CUSTOM_OPP_PATH}}")
    list(GET OPP_PATH_LIST 0 FIRST_OPP_PATH)
    set(CUST_PKG_PATH "${{FIRST_OPP_PATH}}/op_api")
    message(STATUS "env CUST_PKG_PATH: ${{CUST_PKG_PATH}}")
endif()

set(LIB_PATH $ENV{{NPU_HOST_LIB}})

# Dynamic libraries in the stub directory can only be used for compilation
if (NOT DEFINED ENV{{NPU_HOST_LIB}})
    set(LIB_PATH "/usr/local/Ascend/ascend-toolkit/latest/acllib/lib64/stub/")
    set(LIB_PATH1 "/usr/local/Ascend/ascend-toolkit/latest/atc/lib64/stub/")
    message(STATUS "set default LIB_PATH: ${{LIB_PATH}}")
else ()
    message(STATUS "env LIB_PATH: ${{LIB_PATH}}")
endif()

# Header search paths
include_directories(
    ${{INC_PATH}}/runtime/include
    ${{INC_PATH}}/atc/include
    ${{CUST_PKG_PATH}}/include
)

# add host lib path
link_directories(
    ${{LIB_PATH}}
    ${{LIB_PATH1}}
    ${{CUST_PKG_PATH}}/lib
)

# Add the executable target
add_executable({executable_name}
    {self.cpp_filename}
)

# Link necessary libraries to the executable
target_link_libraries({executable_name}
    ascendcl
    cust_opapi
    acl_op_compiler
    nnopbase
    stdc++
)

# This command is useful if you want 'make install' to do something.
# In our simple case, it just copies the executable to the build directory.
install(TARGETS {executable_name} DESTINATION ${{CMAKE_RUNTIME_OUTPUT_DIRECTORY}})
"""